﻿#ifndef __UTILS_H__
#define __UTILS_H__

#include "ZCommon.h"
#include <vector>
#include "ZString.h"

//提供基本容器类
namespace ZuiLib
{
	class ZRenderer;
	typedef uint32_t color_t;

	inline color_t ConvertColor(SDL_Color color)
	{
#ifndef ZBIG_ENDIAN
		uint8_t temp = color.b;
		color.b = color.r;
		color.r = temp;
#endif
		return *(color_t*)(&color);
	}


	//a,r,g,b
	//小根a,b,g,r
	//大根r,g,b,a
	inline SDL_Color ConvertColor(color_t color)
	{
		SDL_Color scolor = *(SDL_Color*)(&color);
#ifndef ZBIG_ENDIAN
		uint8_t temp = scolor.b;
		scolor.b = scolor.r;
		scolor.r = temp;
		return scolor;
#else
		SDL_Color temp;
		temp.a = scolor.r;
		temp.r = scolor.g;
		temp.g = scolor.b;
		temp.b = scolor.a;
		return temp;
#endif
	}

	//转换颜色
	inline color_t MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 0xff) 
	{
		SDL_Color color = {r,g,b,a};
		return ConvertColor(color);
	}

	color_t TextToColor(const char* pstrValue);


	enum LayoutType {
		LT_NONE,
		LT_FILL,//填充
		LT_LEFT,//左边居中
		LT_TOP,
		LT_RIGHT,
		LT_BOTTOM,
		LT_LEFT_TOP,
		LT_RIGHT_TOP,
		LT_LEFT_BOTTOM,
		LT_RIGHT_BOTTOM,
		LT_CENTER,
	};

	const char* LayoutToText(LayoutType type);
	LayoutType TextToLayout(const char* text);

	int GetUTF8FromCodepoint(Uint32 nUChar, char* pszUTF8);
	Uint32 GetCodepointFromUTF8(const char*& c, const char* pszUTF8End = NULL);
	Uint32 GetCodepointFromUTF32(const Uint32*& pstr, const Uint32* pszEnd = NULL);

	typedef struct tagRECT
	{
		int    left;
		int    top;
		int    right;
		int    bottom;
	} RECT, *PRECT, *NPRECT, *LPRECT;

	inline RECT MakeRect(int l, int t,int r,int b) {
		RECT rc = {l,t,r,b};
		return rc;
	}

	typedef struct tagSIZE
	{
		int        cx;
		int        cy;
	} SIZE, *PSIZE, *LPSIZE;

	inline SIZE MakeSize(int x,int y) {
		SIZE sz = { x,y };
		return sz;
	}


	typedef struct tagPOINT
	{
		int  x;
		int  y;
	} POINT, *PPOINT, *NPPOINT, *LPPOINT;

	inline POINT MakePoint(int x, int y) {
		POINT pt = { x,y };
		return pt;
	}

	//RECT Api
	bool PtInRect(const RECT* lprc, POINT lpt);
	bool SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom);
	bool SetRectEmpty(LPRECT lprc);
	bool CopyRect(LPRECT lprcDst, const RECT *lprcSrc);
	bool InflateRect(LPRECT lprc, int dx, int dy);
	bool IntersectRect(LPRECT lprcDst, const RECT *lprcSrc1, const RECT *lprcSrc2);
	bool UnionRect(LPRECT lprcDst, const RECT *lprcSrc1, const RECT *lprcSrc2);

	void InsetRect(LPRECT lprcDst, const RECT *lprcSrc1);

	bool OffsetRect(LPRECT lprc, int dx, int dy);
	bool IsRectEmpty(const RECT *lprc);
	bool EqualRect(const RECT *lprc1, const RECT *lprc2);
	bool JoinRect(RECT *lpdst, const RECT *src);

	extern const RECT  emptyRect;
	extern const POINT emptyPoint;
	extern const SIZE  emptySize;

	//长度值解析，支持dpi
	bool ParserRect(RECT *lpdst, const char *src);
	bool ParserSize(SIZE *lpdst, const char *src);
	bool ParserSize(int *lpdst, const char *src);
	int  ParserSize(const char *src);
	bool ParserPoint(POINT *lpdst, const char *src);
	bool ParserBool(const char* src);

	inline const char* CharNext(const char* ptr)
	{
		if (*ptr == '\0')
			return ptr;
		else
			return (ptr + 1);
	}

#define ZMIN(x, y) (((x) < (y)) ? (x) : (y))
#define ZMAX(x, y) (((x) > (y)) ? (x) : (y))



	class ZPoint :public SDL_Point
	{
	public:
		ZPoint()
		{
			x = y = 0;
		}

		ZPoint(POINT pt)
		{
			x = pt.x;
			y = pt.y;
		}

		ZPoint(int _x, int _y)
		{
			x = _x;
			y = _y;
		}
	};

	class ZSize
	{
	public:
		ZSize()
			:w(0), h(0)
		{
		}

		ZSize(SIZE sz)
			:w(sz.cx), h(sz.cy)
		{
		}

		ZSize(int cx, int cy)
			:w(cx), h(cy)
		{
		}

		inline bool operator==(const ZSize &sz)
		{
			return sz.w == w && sz.h == h;
		}

		inline bool operator!=(const ZSize &sz)
		{
			return sz.w != w || sz.h != h;
		}

		inline bool operator==(const SIZE &sz)
		{
			return sz.cx == w && sz.cy == h;
		}

		inline bool operator!=(const SIZE &sz)
		{
			return sz.cx != w || sz.cy != h;
		}

		int w;
		int h;
	};



	class ZRect :public SDL_Rect
	{
	public:
		ZRect() {
			x = y = w = h = 0;
		}
		ZRect(int _x, int _y, int _w, int _h) {
			x = _x;
			y = _y;
			w = _w;
			h = _h;
		}

		ZRect(SDL_Rect rc)
		{
			x = rc.x;
			y = rc.y;
			w = rc.w;
			h = rc.h;
		}

		ZRect(RECT rc)
		{
			x = rc.left;
			y = rc.top;
			w = rc.right - rc.left;
			h = rc.bottom - rc.top;
		}

		ZRect(ZSize sz)
		{
			x = 0;
			y = 0;
			w = sz.w;
			h = sz.h;
		}

		inline RECT GetCRect()const
		{
			RECT rc = { x,y,x + w,y + h };
			return rc;
		}

		inline void SetSize(ZSize sz)
		{
			w = sz.w;
			h = sz.h;
		}

		inline ZPoint GetPos()const { return ZPoint(x, y); }

		inline int GetWidth() const { return w; }
		inline int GetHeight() const { return h; }
		inline void Empty() { x = y = w = h = 0; }
		inline bool IsNull() const { return (x == 0 && y == 0 && w == 0 && h == 0); }
		inline bool IsEmpty()const { return (w == 0 && h == 0); }
		inline int GetRight()const { return x + w; }
		inline int GetBottom()const { return y + h; }
		inline int GetLeft()const { return x; }
		inline int GetTop()const { return y; }

		//移动矩形
		inline void Offset(int cx, int cy)
		{
			x += cx;
			y += cy;
		}

		bool operator==(const ZRect& rfs)
		{
			return (x == rfs.x && y == rfs.y && w == rfs.w && h == rfs.h);
		}

		ZRect& operator=(const ZRect& rfs)
		{
			x = rfs.x;
			y = rfs.y;
			w = rfs.w;
			h = rfs.h;
			return *this;
		}


		inline bool PtInRect(ZPoint pt)const
		{
			return (pt.x <= x + w && pt.x >= x && pt.y <= y + h && pt.y >= y);
		}
	};

	struct ZScale {
		ZScale()
			:num(1), den(1)
		{
		}

		ZScale(int num_,int den_)
			:num(num_),den(den_)
		{
		}
		int num; ///< Numerator
		int den; ///< Denominator
	};

  //图片绘制信息，高dpi支持，res支持
	struct ZImageDrawInfo {
		enum ImageType{
			IMAGE_TYPE_FILE,//从文件中加载
			IMAGE_TYPE_ATLAS,//从图片集中加载
		};

		//图片倍数
		enum ImageMultiple{
			IMAGE_MULTIPLE_1,
			IMAGE_MULTIPLE_1_5,
			IMAGE_MULTIPLE_2,
			IMAGE_MULTIPLE_3,
		};

		ZImageDrawInfo();
		ZImageDrawInfo(const char* pstr);
		ZImageDrawInfo& operator=(const ZImageDrawInfo&);
		ZImageDrawInfo& operator=(const char* pstr);

		bool LoadImage(ZRenderer* render);
		void Clear();
		bool IsEmpty() {
			return drawString.IsEmpty();
		}
		ZString drawString;

		//高dpi会尝试加载test.png的test@2x.png高倍图，
		//如果加载失败则使用低倍图进行缩放
		ZString image;

		//图片倍率，影响src和scale9的计算，如加载的是test@2x.png则为2
		ImageMultiple multiple;
		ImageType type;
		RECT dest;//支持dpi单位
		RECT bmpPos;//multiple会影响该值
		RECT scale9;//multiple会影响该值
		uint32_t mask;
		int rotate;
		LayoutType layout;
		bool loaded;
	};

	void ScaleRect(LPRECT dest,ZImageDrawInfo::ImageMultiple multiple);

	//////////////////////////////////////////////////////////////////////////////////////////////////
	//array


	class ZPtrArray
	{
	public:
		typedef void* data_t;

		ZPtrArray(int iPreallocSize = 0);
		ZPtrArray(const ZPtrArray& src);
		~ZPtrArray();

		void Empty();
		void Resize(int iSize);
		bool IsEmpty() const;
		int Find(data_t iIndex) const;
		void Add(data_t pData);

		bool SetAt(int iIndex, data_t pData);
		bool InsertAt(int iIndex, data_t pData);

		bool Remove(int iIndex);
		bool Remove(const data_t ptr);

		int GetSize() const;
		data_t GetData();

		data_t GetAt(int iIndex) const;
		data_t operator[] (int nIndex) const;

		data_t Front()const;
		data_t Back()const;

	private:
		typedef std::vector<data_t> container_t;
		container_t m_impl;
	};



	class ZRefPtrArray
	{
	public:
		typedef ZRefCountedBase* data_t;

		ZRefPtrArray(int iPreallocSize = 0);
		ZRefPtrArray(const ZRefPtrArray& src);
		~ZRefPtrArray();

		void Empty();
		void Resize(int iSize);
		bool IsEmpty() const;
		int  Find(data_t iIndex) const;
		void Add(data_t pData);

		bool SetAt(int iIndex, data_t pData);
		bool InsertAt(int iIndex, data_t pData);

		bool Remove(int iIndex);
		bool Remove(const data_t ptr);

		int GetSize() const;
		data_t GetData();

		data_t GetAt(int iIndex) const;
		data_t operator[] (int nIndex) const;

		data_t Front()const;
		data_t Back()const;

	private:
		typedef std::vector<data_t> container_t;
		container_t m_impl;
	};

	template<class T>
	class ZArray
	{
	public:
		ZArray()
		{


		}
		~ZArray()
		{
		
		}

		void Empty()
		{
			m_impl.clear();
		}

		void Resize(int iSize)
		{
			m_impl.resize(iSize);
		}

		bool IsEmpty() const
		{
			return m_impl.empty();
		}

		void Add(const T& data)
		{
			m_impl.push_back(data);
		}

		bool SetAt(int iIndex, const T& data)
		{
			if (iIndex >= 0 && iIndex < m_impl.size())
			{
				m_impl[iIndex] = data;
				return true;
			}
			else
				return false;
		}
		bool InsertAt(int iIndex, const T& data)
		{
			if (iIndex >= 0 && iIndex < m_impl.size())
			{
				m_impl.insert(m_impl.begin() + iIndex, data);
				return true;
			}
			else
				return false;
		}

		bool Remove(int iIndex)
		{
			if (iIndex >= 0 && iIndex < m_impl.size())
			{
				m_impl.erase(m_impl.begin() + iIndex);
				return true;
			}
			else
				return false;
		}

		int GetSize() const
		{
			return m_impl.size();
		}

		const T& GetAt(int iIndex) const
		{
			return m_impl.at(iIndex);
		}

		const T& operator[] (int iIndex) const
		{
			return m_impl.at(iIndex);
		}

	private:
		typedef std::vector<T> container_t;
		container_t m_impl;
	};

	//////////////////////////////////////////////////////////////////////////////////////////////////
	//hashmap
	struct ZStrHashMapImpl;
	class ZStrHashMap
	{
	public:
		typedef void* data_t;

		ZStrHashMap();
		~ZStrHashMap();

		data_t Find(const char* key) const;
		void Set(const char* key, data_t pData);
		bool Remove(const char* key);
		void RemoveAll();
		int GetSize() const;

		class Iterator
		{
		public:
			Iterator(ZStrHashMapImpl* data);
			Iterator(const Iterator& rfs);
			Iterator& operator++();
			bool operator==(const Iterator& rfs);
			bool operator!=(const Iterator& rfs);
			data_t operator*();
			data_t Data();
			const char* Key();
			void SetData(data_t data);
		private:
			friend class ZStrHashMap;
			ZStrHashMapImpl* m_data;
		};

		Iterator Begin();
		Iterator End();
		bool Remove(Iterator* it);
	private:
		DISALLOW_COPY_AND_ASSIGN(ZStrHashMap);
		ZStrHashMapImpl* m_impl;
	};


	//保存引用计数对象
	struct ZRefStrHashMapImpl;
	class ZRefStrHashMap
	{
	public:
		typedef ZRefCountedBase* data_t;

		ZRefStrHashMap();
		~ZRefStrHashMap();

		data_t Find(const char* key) const;
		void Set(const char* key, data_t pData);
		bool Remove(const char* key);
		void RemoveAll();
		int GetSize() const;

		class Iterator
		{
		public:
			Iterator(ZRefStrHashMapImpl* data);
			Iterator(const Iterator& rfs);
			Iterator& operator++();
			bool operator==(const Iterator& rfs);
			bool operator!=(const Iterator& rfs);
			data_t operator*();
			data_t Data();
			const char* Key();
		private:
			ZRefStrHashMapImpl* m_data;
		};

		Iterator Begin();
		Iterator End();
	private:
		DISALLOW_COPY_AND_ASSIGN(ZRefStrHashMap);
		ZRefStrHashMapImpl* m_impl;
	};



	///////////////////////////////////////////////
	//索引为整数的hash表
	struct ZIntHashMapImpl;
	class ZIntHashMap
	{
	public:
		typedef int key_t;
		typedef void* data_t;

		ZIntHashMap();
		~ZIntHashMap();

		data_t Find(key_t key) const;
		void Set(key_t, data_t pData);
		bool Remove(key_t);
		void RemoveAll();
		int GetSize() const;

		class Iterator
		{
		public:
			Iterator(ZIntHashMapImpl* data);
			Iterator(const Iterator& rfs);
			Iterator& operator++();
			bool operator==(const Iterator& rfs);
			bool operator!=(const Iterator& rfs);
			data_t operator*();
			data_t Data();
			key_t Key();
			void SetData(data_t data);
		private:
			friend class ZIntHashMap;
			ZIntHashMapImpl* m_data;
		};

		Iterator Begin();
		Iterator End();
		bool Remove(Iterator* it);
	private:
		DISALLOW_COPY_AND_ASSIGN(ZIntHashMap);
		ZIntHashMapImpl* m_impl;
	};


	//保存引用计数对象
	struct ZRefIntHashMapImpl;
	class ZRefIntHashMap
	{
	public:
		typedef int key_t;
		typedef ZRefCountedBase* data_t;

		ZRefIntHashMap();
		~ZRefIntHashMap();

		data_t Find(key_t key) const;
		void Set(key_t key, data_t pData);
		bool Remove(key_t key);
		void RemoveAll();
		int GetSize() const;

		class Iterator
		{
		public:
			Iterator(ZRefIntHashMapImpl* data);
			Iterator(const Iterator& rfs);
			Iterator& operator++();
			bool operator==(const Iterator& rfs);
			bool operator!=(const Iterator& rfs);
			data_t operator*();
			data_t Data();
			key_t Key();
		private:
			ZRefIntHashMapImpl* m_data;
		};

		Iterator Begin();
		Iterator End();
	private:
		DISALLOW_COPY_AND_ASSIGN(ZRefIntHashMap);
		ZRefIntHashMapImpl* m_impl;
	};

}// namespace ZuiLib

#endif // __UTILS_H__
